package datacontainer;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


/**
 * Immutable container that stores data. It will accept a reference to the
 * data. In other words, it will take the source data and encapsulate it.
 * The object that is creating this Immutable will need to nullify its
 * references to the source data.
 * 
 * @author Michael Deng
 */
public class ImmuTable {
    private List<List<String>> myData;
    private List<String> myHeader;
    private List<String> myType;

    private boolean myUnmodifiableBool = false;

    /**
     * Constructor takes references to all the source data. Immutable will
     * encapsulate this data.
     * 
     * @param headerInput new Header array
     * @param typeInput new Type array
     * @param dataInput new table of data
     */
    public ImmuTable (List<String> headerInput, List<String> typeInput, 
                      List<List<String>> dataInput) {
        myData = dataInput;
        myHeader = headerInput;
        myType = typeInput;
    }

    /**
     * returns headers list
     * 
     * @return List of Headers
     */
    public List<String> getHeaders () {
        return myHeader;
    }

    /**
     * returns types list
     * 
     * @return List of how the associated column is typed (ex. String, double)
     */
    public List<String> getTypes () {
        return myType;
    }

    /**
     * returns unmodifiable list of column
     * 
     * @param column index of column of interest
     * @return specified column from the table
     */
    public List<String> getColumn (int column) {
        return Collections.unmodifiableList(myData.get(column));
    }

    /**
     * returns unmodifiable version of row
     * 
     * @param row index of row of interest
     * @return specified row from the table
     */
    public List<String> getRow (int row) {
        List<String> rowarray = new ArrayList<String>();
        for (List<String> a : myData) {
            rowarray.add(a.get(row));
        }
        return Collections.unmodifiableList(rowarray);
    }

    /**
     * returns number of rows
     * 
     * @return number of rows
     */
    public int getNumRows () {
        return myData.get(0).size();
    }

    /**
     * returns number of columns
     * 
     * @return number of columns
     */
    public int getNumColumns () {
        return myData.size();
    }

    /**
     * returns myData
     * 
     * @return myData
     */
    public List<List<String>> getData () {
        return myData;
    }

    /**
     * makes the data structures unmodifiable
     * 
     * @return true when ImmuTable is unmodifiable
     */
    public boolean makeUnmodifiable () {

        if (!myUnmodifiableBool) {
            myHeader = Collections.unmodifiableList(myHeader);
            myType = Collections.unmodifiableList(myType);

            for (int i = 0; i < myData.size(); i++) {
                myData.set(i, Collections.unmodifiableList(myData.get(i)));
            }

            myData = Collections.unmodifiableList(myData);
            myUnmodifiableBool = true;
        }

        return myUnmodifiableBool;
    }
}
